{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Making screenshots programmatically\n",
    "\n",
    "Making screenshots on the frontent triggered by `plot.fetch_screenshot()` requires special care.\n",
    "1. One needs to wait for data before it is synchronized. \n",
    "2. Before calling `plot.fetch_screenshot()` the plot object must be displayed.\n",
    "\n",
    "To change dpi of the image one can use for example: `plot.screenshot_scale = 4.0`.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Notice\n",
    "\n",
    "That method of getting screenshots is obsolete. Much better way is to use headless solution (headless.ipynb)\n",
    "\n",
    "I leave here that method because that is still way to go. In that method we have strong assumption that each frames have at least tiny difference between themself"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import k3d\n",
    "import numpy as np\n",
    "from IPython.display import Image\n",
    "\n",
    "points_number = 15\n",
    "spread_range = 30\n",
    "positions = spread_range * np.random.random_sample((points_number, 3)) - spread_range / 2\n",
    "colors = np.random.randint(0, 0xFFFFFF, points_number)\n",
    "\n",
    "plot = k3d.plot(height=240)\n",
    "points = k3d.points(positions.astype(np.float32), colors.astype(np.uint32), point_size=3.0, shader='mesh')\n",
    "plot += points\n",
    "\n",
    "plot.display()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Single screenshot\n",
    "\n",
    "First, let's generate a single screenshot:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plot.fetch_screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note**: this operation is asynchronous.\n",
    "\n",
    "We need to wait for the widgets to synchronize behind the scenes, before calling the next cell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('screenshot.png', 'wb') as f:\n",
    "    try:\n",
    "        out = plot.screenshot.decode('base64')\n",
    "    except: # Python 3\n",
    "        from base64 import b64decode\n",
    "        out = b64decode(plot.screenshot)    \n",
    "    f.write(out)\n",
    "    \n",
    "Image(url='screenshot.png')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Multiple screenshots \n",
    "\n",
    "\n",
    "If we want to generate many screenshots within a single cell, it is possible to do it in a following way:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ipywidgets\n",
    "\n",
    "plot.camera_auto_fit = False\n",
    "plot.grid_auto_fit = False\n",
    "\n",
    "speeds = -0.5 * np.sign(positions)\n",
    "out = ipywidgets.Output()\n",
    "\n",
    "@plot.yield_screenshots\n",
    "def coroutine():\n",
    "    global positions\n",
    "    for i in range(12):\n",
    "        positions += speeds\n",
    "        points.positions = positions.astype(np.float32)\n",
    "        plot.fetch_screenshot()\n",
    "        screenshot = yield\n",
    "        with open('screenshot_%03d.png'%i, 'wb') as f:\n",
    "            f.write(screenshot)\n",
    "        with out:\n",
    "            print('screenshot_%03d.png saved.'%i)\n",
    "    with out:\n",
    "        print('done.')\n",
    "\n",
    "coroutine()\n",
    "print('loop is running in background...')\n",
    "out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!convert screenshot_*.png screenshot.gif && rm screenshot_*.png"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "Image('screenshot.gif')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  },
  "nbTranslate": {
   "displayLangs": [
    "en",
    "pl"
   ],
   "hotkey": "alt-t",
   "langInMainMenu": true,
   "sourceLang": "pl",
   "targetLang": "en",
   "useGoogleTranslate": true
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
